package com.db.transport.report;

import com.db.transport.SessionFactory;
import com.db.transport.client.SessionClient;
import com.db.transport.exchange.SessionExchange;
import com.db.transport.report.listener.SessionReportListener;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Logger;

/**
 * @author nulls.narik
 */
public class SessionReport {

    private static Logger logger = Logger.getLogger(SessionReport.class.getName());

    private final ServerSocket serverSocketForClient;
    private final ServerSocket serverSocketForExchange;

    private volatile boolean isShutdown;

    public SessionReport(int portForClients, int portForExchange) throws IOException {
        serverSocketForClient = new ServerSocket(portForClients);
        serverSocketForExchange = new ServerSocket(portForExchange);

        listeners = new CopyOnWriteArraySet<SessionReportListener>();
        isShutdown = false;
    }

    public void startConnectingNewClients() {
        threadForNewClient.start();
    }

    private Thread threadForNewClient = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!isShutdown && !Thread.currentThread().isInterrupted()) {
                try {
                    Socket socket = serverSocketForClient.accept();
                    PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String clientID = reader.readLine();
                    Integer typeAggregation = new Integer(reader.readLine());
                    Long timer = new Long(reader.readLine());
                    newClient(clientID, typeAggregation, timer, SessionFactory.getSessionClient(clientID, socket, reader, writer));
                    logger.info(String.format("Report: new client: %s", clientID));
                } catch (IOException e) {
                    logger.warning("Report: error when try connect with new client");
                }
            }
        }
    });

    public void startConnectingNewExchange() {
        threadForNewExchange.start();
    }

    private Thread threadForNewExchange = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!isShutdown && !Thread.currentThread().isInterrupted()) {
                try {
                    Socket socket = serverSocketForExchange.accept();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
                    String exchangeID = reader.readLine();
                    // новая биржа
                    SessionExchange sessionExchange = new SessionExchange(exchangeID, socket, reader, writer);
                    newExchange(exchangeID, sessionExchange);
                    logger.info(String.format("Report: new exchange: %s", exchangeID));
                } catch (IOException e) {
                    logger.warning("Report: error when try connect with new exchange");
                }
            }
        }
    });

    public void shutdown() {
        isShutdown = true;
    }

    private final Set<SessionReportListener> listeners;

    public void addListener(SessionReportListener listener) {
        listeners.add(listener);
    }

    public void newClient(String clientID, Integer typeAggregation, Long timer, SessionClient sessionClient) {
        Iterator<SessionReportListener> iterator = listeners.iterator();
        while (iterator.hasNext()) {
            iterator.next().newClient(clientID, typeAggregation, timer, sessionClient);
        }
    }

    public void newExchange(String exchangeID, SessionExchange sessionExchange) {
        Iterator<SessionReportListener> iterator = listeners.iterator();
        while (iterator.hasNext()) {
            iterator.next().newExchange(exchangeID, sessionExchange);
        }
    }

}
